#!/usr/bin/env python

import random
import os
from google.appengine.ext.webapp import template
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext import db

class Bmark(db.Model):
    title = db.StringProperty()
    tags = db.StringListProperty() #deprecated
    url = db.LinkProperty()
    hash = db.IntegerProperty() #speed lookup when insert a new bookmark
    date = db.DateTimeProperty(auto_now_add = True)
    
class User(db.Model):
    username = db.StringProperty() #google account username or provided by user
    
class Comment(db.Model):
    markkey = db.ReferenceProperty(Bmark)
    comment = db.StringProperty(multiline = True)
    date = db.DateTimeProperty(auto_now_add = True)
    
class Record(db.Model): #user's activity on bookmarks
    userkey = db.ReferenceProperty(User)
    markkey = db.ReferenceProperty(Bmark)
    like = db.BooleanProperty() #like or dislike

class Tag(db.Model):
    hash = db.IntegerProperty() #speed lookup
    value = db.StringProperty()
    count = db.IntegerProperty(required = True, default = 1)
    
class BmarkTag(db.Model):
    markkey = db.ReferenceProperty(Bmark)
    tagkey = db.ReferenceProperty(Tag)
    count = db.IntegerProperty(required = True, default = 1) #tagged count times by different people
               
class Statistic(db.Model):
    markkey = db.ReferenceProperty(Bmark)
    up = db.IntegerProperty(required = True, default = 0)
    down = db.IntegerProperty(required = True, default = 0)
    popularity = db.IntegerProperty(required = True, default = 0)
    
class ShowHandler(webapp.RequestHandler):
    def get(self):
        offset = self.request.get("offset")
        try:        
            offset = int(offset)
            if (offset < 0):
                offset = 0
        except:
            offset = 0
            
        BATCH = 20
        
        bmarks = Bmark.all().order('-date').fetch(BATCH, offset)
        temp = Bmark.all().order('-date').fetch(BATCH, offset + BATCH)
        hasprev = hasnext = False
        prevoff = nextoff = 0
        
        if offset > 0 and len(bmarks) > 0:
            hasprev = True
            prevoff = offset - BATCH
            
        if len(bmarks) == BATCH and len(temp) > 0:
            hasnext = True
            nextoff = offset + BATCH
        
        nexturl = "/?offset=" + str(nextoff) + "&x=" + str(random.uniform(10, 20))
        template_values = {'bmarks': bmarks, "hasprev": hasprev, 
                           "hasnext": hasnext, "prevoff": prevoff,
                           "nextoff": nextoff, "nexturl": nexturl}
        
        path = os.path.join(os.path.dirname(__file__), "index.html")
        self.response.out.write(template.render(path, template_values))
      
class InputHandler(webapp.RequestHandler):
    def get(self):
        user = users.get_current_user()
        path = os.path.join(os.path.dirname(__file__), "input.html")
        if user:
            self.response.out.write(template.render(path, {}))
        else:
            self.redirect(users.create_login_url("/input"))
        
          
class MarkHandler(webapp.RequestHandler):
    def post(self): 
        user = users.get_current_user()
        username = "anonymous"
        if user:
            username = user.email()
        else:
            self.redirect(users.create_login_url("/input.html"))
        
        mark = Bmark()
        mark.title = self.request.get("title")
        if len(mark.title.strip()) == 0:
            self.response.out.write("Title should not be empty")
            return
            
        tags = self.request.get("tags").split(',')
        try:
            mark.url = self.request.get("url")
        except:
            self.response.out.write("Invalide Url")
            return
            
        mark.hash = hash(mark.url)
        
        #handle the same url
        m = Bmark.all().filter("hash", mark.hash).filter("url", mark.url).get()
        if m:
            markkey = m.key()
        else:
            markkey = mark.put()

        #handle the same username
        u = User.all().filter("username", username).get()
        if u:
            userkey = u.key()
        else:
            u = User()
            u.username = username
            userkey = u.put()                
        
        r = Record.all().filter("userkey", userkey).filter("markkey", markkey).get()
        if r:#already bookmarked this url 
            pass
        else:
            r = Record()
            r.userkey = userkey
            r.markkey = markkey
            r.like = True
            r.put()
            
            s = Statistic.all().filter("markkey", markkey).get()
            if s is None:
                s = Statistic()
                s.markkey = markkey

            s.up += 1
            s.popularity += 1
            s.save()
        
        for t in tags:
            th = hash(t)
            te = Tag.all().filter("hash", th).filter("value", t).get()
            if te:
                te.count += 1
            else:
                te = Tag()
                te.hash = th
                te.value = t
            tagkey = te.save()
            
            bt = BmarkTag.all().filter("markkey", markkey).filter("tagkey", tagkey).get()
            if bt:
                bt.count += 1
            else:
                bt = BmarkTag()
                bt.markkey = markkey
                bt.tagkey = tagkey
            bt.save()

        self.redirect("/")
            
class UpHandler(webapp.RequestHandler):
    def post(self):
        pass
    
class DownHandler(webapp.RequestHandler):
    def post(self):
        pass
    
class DeleteHandler(webapp.RequestHandler):
    def post(self):
        pass        

def main():
    application = webapp.WSGIApplication([('/', ShowHandler),
                                          ('/input', InputHandler),
                                          ('/mark', MarkHandler),
                                          ('/up', UpHandler),
                                          ('/down', DownHandler),
                                          ('/delete', DeleteHandler)
                                         ],debug=True)
    util.run_wsgi_app(application)


if __name__ == '__main__':
    main()
